package com.eastfair.gateway.filters;

import com.alibaba.fastjson.JSONObject;
import com.eastfair.core.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.reactivestreams.Publisher;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.Charset;
import java.util.Date;

@Slf4j
@Component
public class LogFilter implements GlobalFilter, Ordered{
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        try {
            Date startTime =new Date();
            //记录接口调用情况
            JSONObject logJsonObject = new JSONObject();
//            StringBuilder logBuilder = new StringBuilder();
            StringBuilder requestBody=new StringBuilder();
            ServerHttpRequest serverHttpRequest = exchange.getRequest();
            String method = serverHttpRequest.getMethodValue().toUpperCase();
            //方法
            logJsonObject.put("method",method);
            //开始时间
            logJsonObject.put("startTime",DateUtils.format(startTime,"yyyy-MM-dd HH:mm:ss"));
            logJsonObject.put("url",serverHttpRequest.getURI());
            if ("POST".equals(method)) {
                requestBody.append(exchange.getAttributeOrDefault("cachedRequestBody", ""));
                if (StringUtils.isNotBlank(requestBody)) {
                    logJsonObject.put("body",requestBody);
                }
            }else if("GET".equals(method)){
                MultiValueMap<String, String> queryParams = serverHttpRequest.getQueryParams();
                logJsonObject.put("body",JSONObject.toJSONString(queryParams));
                requestBody.append(JSONObject.toJSONString(queryParams));
            }
            ServerHttpResponse serverHttpResponse = exchange.getResponse();
            DataBufferFactory bufferFactory = serverHttpResponse.bufferFactory();
            ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(serverHttpResponse) {
                @Override
                public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                    String originalResponseContentType = exchange.getAttribute("original_response_content_type");
                    if (body instanceof Flux && StringUtils.isNotBlank(originalResponseContentType) && originalResponseContentType.contains("application/json")) {
                        Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
                        return super.writeWith(fluxBody.map(dataBuffer -> {
                            byte[] content = new byte[dataBuffer.readableByteCount()];
                            dataBuffer.read(content);
                            DataBufferUtils.release(dataBuffer);
                            try {
                                String resp = new String(content, Charset.forName("UTF-8"));
                                Date endTime = new Date();
                                //保存日志到数据库
//                                buildLog(exchange, requestBody.toString(),resp,startTime,endTime);
                                logJsonObject.put("result",resp);

                                //结束时间
                                logJsonObject.put("endTime", DateUtils.format(endTime,"yyyy-MM-dd HH:mm:ss"));
                                //执行时间
                                logJsonObject.put("runTime",endTime.getTime() - startTime.getTime());
                            }catch (Exception e){
                                log.info("save log err!");
                                log.info(e.getMessage(),e);
                            }
                            log.info(logJsonObject.toString());
                            // TODO: 2021/8/23  可以将接口调用情况，埋点到mongo中
                            byte[] uppedContent = new String(content, Charset.forName("UTF-8")).getBytes();
                            return bufferFactory.wrap(uppedContent);
                        }));
                    }
                    return super.writeWith(body);
                }
            };
            return chain.filter(exchange.mutate().response(decoratedResponse).build());
        }catch (Exception e){
            log.info("logfilter exception!");
            log.info(e.getMessage(),e);
        }
        return chain.filter(exchange);

    }
    @Override
    public int getOrder() {
        return -20;
    }
}
